package com.sky.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sky.blog.dao.dto.PostsPageDTO;
import com.sky.blog.dao.enums.StatusCode;
import com.sky.blog.dao.mapper.PostsMapper;
import com.sky.blog.dao.pojo.Posts;
import com.sky.blog.dao.vo.BlogFocusVo;
import com.sky.blog.dao.vo.PostListVo;
import com.sky.blog.service.PostsService;
import com.sky.blog.util.DozerUtils;
import com.sky.blog.util.PageUtils;
import com.sky.blog.vo.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author sky  2022/3/23
 * @version 1.0
 */
@Slf4j
@Service("postsService")
public class PostsServiceImpl implements PostsService {

    @Resource
    private PostsMapper postsMapper;

    /**
     * <ol>
     *     <li>判断{@link com.sky.blog.dao.dto.PostsPageDTO}的分页和页大小是否合法 并创建分页</li>
     *     <li>创建查询包装器</li>
     *     <li>如果分类不为空就 按分类相似查询</li>
     *     <li>查询已发布</li>
     *     <li><span>如果搜索字段不为空就按下列字段相似搜索</span>
     *          <ul>
     *              <li>标题</li>
     *              <li>正文</li>
     *              <li>摘要</li>
     *          </ul>
     *     </li>
     *     <li><span>显示顺序按以下</span>
     *     <ul>
     *         <li>置顶降序</li>
     *         <li>热度降序</li>
     *         <li>发布时间降序</li>
     *     </ul></li>
     *     <li>将查询结果封装为{@link com.sky.blog.dao.vo.PostListVo}</li>
     * </ol>
     *
     * @param postsPageDTO 控制层传入的查询条件
     * @return 封装的分页类
     */
    @Override
    public PageResult<PostListVo> selectListPage(PostsPageDTO postsPageDTO) {
        Page<Posts> postsPage = getPostsPage(postsPageDTO);
        List<PostListVo> collect = postsPage.getRecords().stream()
                .map(posts -> DozerUtils.copy(posts, PostListVo.class))
                .collect(Collectors.toList());
        return PageUtils.buildResponse(postsPage, collect);
    }

    @Override
    public List<BlogFocusVo> selectListBlogFocus() {
        Page<Posts> focusPage = this.getPostsPage(new PostsPageDTO(0, 3));
        return focusPage.getRecords().stream().map(list -> DozerUtils.copy(list, BlogFocusVo.class)).collect(Collectors.toList());
    }


    private Page<Posts> getPostsPage(PostsPageDTO postsPageDTO) {
        initPagination(postsPageDTO);
        Page<Posts> postsPage = new Page<>(postsPageDTO.getPageNum(), postsPageDTO.getPageSize());

        LambdaQueryWrapper<Posts> wrapper = Wrappers.lambdaQuery(Posts.class);

        wrapper.func(queryWrapper -> {
            if (StringUtils.isNotBlank(postsPageDTO.getCategory())) {
                queryWrapper.like(Posts::getCategory, postsPageDTO.getCategory());
            }
        }).func(queryWrapper -> {
            if (StringUtils.isNotBlank(postsPageDTO.getSearchWords())) {
                queryWrapper.and(i -> {
                            i.like(Posts::getTitle, postsPageDTO.getSearchWords());
                        }).or().like(Posts::getContent, postsPageDTO.getSearchWords())
                        .or().like(Posts::getSummary, postsPageDTO.getSearchWords());
            }
        });
        wrapper.and(i -> i.eq(Posts::getStatus, StatusCode.NORMAL));
        wrapper.orderByDesc(Posts::getIsTop);
        wrapper.orderByDesc(Posts::getIsHot);
        wrapper.orderByDesc(Posts::getViewsCount);
        wrapper.orderByDesc(Posts::getPublishTime);

        try {
            postsPage = postsMapper.selectPage(postsPage, wrapper);
        } catch (Exception e) {
            log.error("查询失败:{}", e.getMessage());
        }
        return postsPage;
    }


    private void initPagination(PostsPageDTO postsPageDTO) {

        if (postsPageDTO.getPageNum() == null || postsPageDTO.getPageNum() < 0) {
            postsPageDTO.setPageNum(1);
        }

        if (postsPageDTO.getPageSize() == null || postsPageDTO.getPageSize() < 0) {
            postsPageDTO.setPageSize(8);
        }
    }
}
